package concurrecy;

import java.util.Random;
import java.util.concurrent.*;
import java.util.concurrent.locks.LockSupport;

class MyFutureTask<T> implements Runnable {
    private Callable<T> callable;
    private T value;
    private LinkedBlockingQueue<Thread> waiters = new LinkedBlockingQueue<>();

    private volatile State state = State.NEW;

    enum State {
        // 新建
        NEW,
        // 数据已经准备好
        READY
    }

    public MyFutureTask(Callable<T> callable) {
        this.callable = callable;
    }

    public T get() {
        // 数据还没准备好，阻塞当前线程，并加入到等待队列
        while(state != State.READY) {
            waiters.add(Thread.currentThread());
            LockSupport.park();
        }
        return value;
    }

    @Override
    public void run() {
        try {
            value = callable.call();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 数据准备好了
            state = State.READY;
            // 通知所有线程
            do {
                Thread thread = waiters.poll();
                if(thread != null)
                    LockSupport.unpark(thread);
            } while(!waiters.isEmpty());
        }
    }
}

/**
 * 自己实现一个 FutureTask
 */
public class FutureTaskDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Callable<Integer> callable = new Callable<Integer>() {
            private Random random = new Random();
            @Override
            public Integer call() throws Exception {
                return random.nextInt(100);
            }
        };
        MyFutureTask<Integer> futureTask = new MyFutureTask<>(callable);
        new Thread(futureTask).start();
        System.out.println(futureTask.get());
    }
}
